package adapter

import (
	"encoding/json"
	"errors"
	"migration-tool/adapter/gitee"
	"migration-tool/common"
	"os"
	"regexp"
	"strconv"
	"sync"
)

const (
	AonePlatformName   = "aone"
	GiteePlatformName  = "gitee"
	GitLabPlatformName = "gitlab"

	CodeupPlatformName  = "codeup"
	AtomGitPlatformName = "atomgit"

	MergeNameMergeRequest = "MergeRequest"
	MergeNameUser         = "User"
	MergeNameIssue        = "Issue"

	MergeProgressFileName  = "merge-progress.json"
	ImportProgressFileName = "import-progress.json"
	ExportProgressFileName = "export-progress.json"

	defaultOrderNum = 10
)

var exportPlatform map[string]struct{}

var GetAllRepoInfoFuncMap map[string]func(cfg *common.Config) (RepoInfoArray, error)
var MergeFuncMap map[string]map[string]func(cfg *common.Config) error

// 分库函数的Map，FuncMaps的Key为平台，Value为导入/导出的函数map
var FuncMaps map[string]map[string]func(args TaskArgs) error
var CheckFuncMap map[string]map[string]func(args TaskArgs) error
var GlobalFuncMaps map[string]map[string]func(args TaskArgs) error
var GlobalCheckFuncMaps map[string]map[string]func(args TaskArgs) error
var importPlatformMap map[string]string

var defaultOrder map[string]int
var userRelatedTasks map[string]struct{}

func init() {
	exportPlatform = make(map[string]struct{})
	exportPlatform[AonePlatformName] = struct{}{}
	exportPlatform[GiteePlatformName] = struct{}{}
	//exportPlatform[GitLabPlatformName] = struct{}{}

	importPlatformMap = make(map[string]string)
	importPlatformMap[AonePlatformName] = CodeupPlatformName
	importPlatformMap[GiteePlatformName] = AtomGitPlatformName

	FuncMaps = make(map[string]map[string]func(args TaskArgs) error)
	GlobalFuncMaps = make(map[string]map[string]func(args TaskArgs) error)
	GlobalCheckFuncMaps = make(map[string]map[string]func(args TaskArgs) error)

	aoneMergeFuncMap := make(map[string]func(cfg *common.Config) error)
	aoneMergeFuncMap[MergeNameMergeRequest] = aoneMergeAllMergeRequests
	aoneMergeFuncMap[MergeNameUser] = aoneMergeAllUsers
	giteeMergeFuncMap := make(map[string]func(cfg *common.Config) error)
	giteeMergeFuncMap[MergeNameUser] = giteeMergeAllUsers
	//giteeMergeFuncMap[MergeNameMergeRequest] = giteeMergeAllMergeRequests
	//giteeMergeFuncMap[MergeNameIssue] = giteeMergeAllIssues
	MergeFuncMap = make(map[string]map[string]func(cfg *common.Config) error)
	MergeFuncMap[AonePlatformName] = aoneMergeFuncMap
	MergeFuncMap[GiteePlatformName] = giteeMergeFuncMap

	userRelatedTasks = make(map[string]struct{})
	userRelatedTasks[TaskNameRepoMember] = struct{}{}
	userRelatedTasks[TaskNameMergeRequest] = struct{}{}
	userRelatedTasks[TaskNameIssue] = struct{}{}

	GetAllRepoInfoFuncMap = make(map[string]func(cfg *common.Config) (RepoInfoArray, error))
	GetAllRepoInfoFuncMap[AonePlatformName] = aoneGetAllRepoInfo
	GetAllRepoInfoFuncMap[GiteePlatformName] = giteeGetAllRepoInfo

	aoneTaskFuncMap := make(map[string]func(args TaskArgs) error)
	aoneTaskFuncMap[TaskNameMergeRequest] = aoneDealMergeRequest
	aoneTaskFuncMap[TaskNameWiki] = aoneDealWiki
	aoneTaskFuncMap[TaskNameCode] = aoneDealCode
	aoneTaskFuncMap[TaskNameRepoMember] = aoneDealRepoMember
	aoneTaskFuncMap[TaskNameRepoMetaInfo] = aoneDealRepoMetaInfo
	aoneTaskFuncMap[TaskNameDeployKeysSetting] = aoneDealDeployKeySetting
	aoneTaskFuncMap[TaskNameWebHookSetting] = aoneDealWebHookSetting
	aoneTaskFuncMap[TaskNamePushRuleSetting] = aoneDealPushRuleSetting
	aoneTaskFuncMap[TaskNameCodeReviewSetting] = aoneDealCodeReviewSetting
	aoneTaskFuncMap[TaskNameProtectBranchSetting] = aoneDealProtectBranchSetting
	FuncMaps[AonePlatformName] = aoneTaskFuncMap
	aoneGlobalTaskFuncMap := make(map[string]func(args TaskArgs) error)
	aoneGlobalTaskFuncMap[GlobalTaskNameGroup] = aoneDealGroup
	aoneGlobalTaskFuncMap[GlobalTaskNameGroupMember] = aoneDealGroupMember
	GlobalFuncMaps[AonePlatformName] = aoneGlobalTaskFuncMap

	giteeTaskFuncMap := make(map[string]func(args TaskArgs) error)
	giteeTaskFuncMap[TaskNameWiki] = giteeDealWiki
	giteeTaskFuncMap[TaskNameCode] = giteeDealCode
	giteeTaskFuncMap[TaskNameRepoMember] = giteeDealRepoMember
	giteeTaskFuncMap[TaskNameRepoMetaInfo] = giteeDealRepoMetaInfo
	giteeTaskFuncMap[TaskNameDeployKeysSetting] = giteeDealDeployKeySetting
	giteeTaskFuncMap[TaskNameWebHookSetting] = giteeDealWebHookSetting
	giteeTaskFuncMap[TaskNamePushRuleSetting] = giteeDealPushRuleSetting
	giteeTaskFuncMap[TaskNameCodeReviewSetting] = giteeDealCodeReviewSetting
	giteeTaskFuncMap[TaskNameProtectBranchSetting] = giteeDealProtectBranchSetting
	giteeTaskFuncMap[TaskNameRelease] = giteeDealRelease
	giteeTaskFuncMap[TaskNameMileStone] = giteeDealMileStone
	giteeTaskFuncMap[TaskNameMergeRequest] = giteeDealMergeRequest
	giteeTaskFuncMap[TaskNameIssue] = giteeDealIssue
	FuncMaps[GiteePlatformName] = giteeTaskFuncMap
	giteeGlobalTaskFuncMap := make(map[string]func(args TaskArgs) error)
	giteeGlobalTaskFuncMap[GlobalTaskNameGroup] = globalGiteeDealGroup
	giteeGlobalTaskFuncMap[GlobalTaskNameGroupMember] = globalGiteeDealGroupMember
	giteeGlobalTaskFuncMap[GlobalTaskNameEnterprise] = globalGiteeDealEnterprise
	giteeGlobalTaskFuncMap[GlobalTaskNameEnterpriseMember] = globalGiteeDealEnterpriseMember
	giteeGlobalTaskFuncMap[GlobalTaskNameLabel] = globalGiteeDealLabel
	GlobalFuncMaps[GiteePlatformName] = giteeGlobalTaskFuncMap

	codeupTaskFuncMap := make(map[string]func(args TaskArgs) error)
	codeupTaskFuncMap[TaskNameCode] = codeupDealCode
	codeupTaskFuncMap[TaskNameWiki] = codeupDealWiki
	codeupTaskFuncMap[TaskNameRepoMember] = codeupDealRepoMember
	codeupTaskFuncMap[TaskNameRepoMetaInfo] = codeupDealRepoMetaInfo
	codeupTaskFuncMap[TaskNameDeployKeysSetting] = codeupDealDeployKeysSetting
	codeupTaskFuncMap[TaskNameWebHookSetting] = codeupDealWebHookSetting
	codeupTaskFuncMap[TaskNamePushRuleSetting] = codeupDealPushRuleSetting
	codeupTaskFuncMap[TaskNameCodeReviewSetting] = codeupDealCodeReviewSetting
	codeupTaskFuncMap[TaskNameProtectBranchSetting] = codeupDealProtectBranchSetting
	codeupTaskFuncMap[TaskNameMergeRequest] = codeupDealMergeRequest
	FuncMaps[CodeupPlatformName] = codeupTaskFuncMap
	codeupGlobalTaskFuncMap := make(map[string]func(args TaskArgs) error)
	codeupGlobalTaskFuncMap[GlobalTaskNameGroupMember] = globalCodeupDealGroupMember
	codeupGlobalTaskFuncMap[GlobalTaskNameUser] = globalCodeupDealUser
	GlobalFuncMaps[CodeupPlatformName] = codeupGlobalTaskFuncMap

	atomGitTaskFuncMap := make(map[string]func(args TaskArgs) error)
	atomGitTaskFuncMap[TaskNameCode] = atomGitDealCode
	atomGitTaskFuncMap[TaskNameWiki] = atomGitDealWiki
	atomGitTaskFuncMap[TaskNameRepoMember] = atomGitDealRepoMember
	atomGitTaskFuncMap[TaskNameRepoMetaInfo] = atomGitDealRepoMetaInfo
	atomGitTaskFuncMap[TaskNameDeployKeysSetting] = atomGitDealDeployKeysSetting
	atomGitTaskFuncMap[TaskNameWebHookSetting] = atomGitDealWebHookSetting
	atomGitTaskFuncMap[TaskNamePushRuleSetting] = atomGitDealPushRuleSetting
	atomGitTaskFuncMap[TaskNameCodeReviewSetting] = atomGitDealCodeReviewSetting
	atomGitTaskFuncMap[TaskNameProtectBranchSetting] = atomGitDealProtectBranchSetting
	atomGitTaskFuncMap[TaskNameRelease] = atomGitDealRelease
	atomGitTaskFuncMap[TaskNameMileStone] = atomGitDealMileStone
	atomGitTaskFuncMap[TaskNameMergeRequest] = atomGitDealMergeRequest
	atomGitTaskFuncMap[TaskNameIssue] = atomGitDealIssue
	FuncMaps[AtomGitPlatformName] = atomGitTaskFuncMap
	atomGitGlobalTaskFuncMap := make(map[string]func(args TaskArgs) error)
	atomGitGlobalTaskFuncMap[GlobalTaskNameGroup] = globalAtomGitDealGroup
	atomGitGlobalTaskFuncMap[GlobalTaskNameGroupMember] = globalAtomGitDealGroupMember
	atomGitGlobalTaskFuncMap[GlobalTaskNameUser] = globalAtomGitDealUser
	atomGitGlobalTaskFuncMap[GlobalTaskNameLabel] = globalAtomGitDealLabel
	atomGitGlobalTaskFuncMap[GlobalTaskNameEnterprise] = globalAtomGitDealEnterprise
	atomGitGlobalTaskFuncMap[GlobalTaskNameEnterpriseMember] = globalAtomGitDealEnterpriseMember
	GlobalFuncMaps[AtomGitPlatformName] = atomGitGlobalTaskFuncMap

	CheckFuncMap = make(map[string]map[string]func(args TaskArgs) error)
	atomGitCheckFunc := make(map[string]func(args TaskArgs) error)
	atomGitCheckFunc[TaskNameCode] = checkRepoCodeConsistent
	atomGitCheckFunc[TaskNameWiki] = checkRepoWikiConsistent
	atomGitCheckFunc[TaskNameRepoMetaInfo] = checkRepoMetaInfoConsistent
	atomGitCheckFunc[TaskNameRepoMember] = checkRepoMemberConsistent
	atomGitCheckFunc[TaskNameProtectBranchSetting] = checkProtectBranchSettingConsistent
	atomGitCheckFunc[TaskNameRelease] = checkReleaseConsistent
	atomGitCheckFunc[TaskNameMileStone] = checkMileStoneConsistent
	atomGitCheckFunc[TaskNameMergeRequest] = checkMergeRequestConsistent
	atomGitCheckFunc[TaskNameIssue] = checkIssueConsistent

	CheckFuncMap[GiteePlatformName] = atomGitCheckFunc
	atomGitGlobalCheckFuncMap := make(map[string]func(args TaskArgs) error)
	atomGitGlobalCheckFuncMap[GlobalTaskNameUser] = checkUserConsistent
	atomGitGlobalCheckFuncMap[GlobalTaskNameLabel] = checkLabelConsistent
	atomGitGlobalCheckFuncMap[GlobalTaskNameGroupMember] = checkGroupMemberConsistent
	GlobalCheckFuncMaps[AtomGitPlatformName] = atomGitGlobalCheckFuncMap
}

func init() {
	defaultOrder = make(map[string]int)
	defaultOrder[TaskNameCode] = defaultOrderNum
	defaultOrder[TaskNameWiki] = defaultOrderNum
	defaultOrder[TaskNameMergeRequest] = defaultOrderNum
	defaultOrder[TaskNameIssue] = defaultOrderNum
	defaultOrder[TaskNameRepoMetaInfo] = defaultOrderNum
	defaultOrder[TaskNameRepoMember] = defaultOrderNum
	defaultOrder[TaskNameCodeReviewSetting] = defaultOrderNum
	defaultOrder[TaskNamePushRuleSetting] = defaultOrderNum
	defaultOrder[TaskNameWebHookSetting] = defaultOrderNum
	defaultOrder[TaskNameDeployKeysSetting] = defaultOrderNum
	defaultOrder[TaskNameProtectBranchSetting] = defaultOrderNum
	defaultOrder[TaskNameRelease] = defaultOrderNum
	defaultOrder[TaskNameMileStone] = defaultOrderNum
}

func AssignDefaultOrder(cfg *common.Config) {
	if cfg.BaseConfig.Order == nil {
		cfg.BaseConfig.Order = make(map[string]int)
	}

	// 导出时，顺序配置无效，可以并行进行
	// 导入时，严格按照defaultOrder进行
	for taskName, order := range defaultOrder {
		if _, ok := cfg.BaseConfig.Order[taskName]; (!ok && !cfg.BaseConfig.Export) || cfg.BaseConfig.Export {
			cfg.BaseConfig.Order[taskName] = order
		}
	}
}

func GetPlatformName(platformName string) string {
	if _, ok := exportPlatform[platformName]; ok {
		return platformName
	}
	panic(ErrorMsgPlatFormNameError)
}

// CreateOneAdapter 创建一个default_adapter
func CreateOneAdapter(cfg *common.Config, args DefaultAdapterArgs) (Adapter, error) {
	_ = GetPlatformName(cfg.BaseConfig.ExportPlatformName)
	return makeDefaultAdapter(cfg, args)
}

// GetAllRepoInfo
// 获取所有的仓库信息，导入导出通用
func GetAllRepoInfo(cfg *common.Config) (RepoInfoArray, error) {
	platformName := GetPlatformName(cfg.BaseConfig.ExportPlatformName)
	if _, ok := GetAllRepoInfoFuncMap[platformName]; ok {
		return GetAllRepoInfoFuncMap[platformName](cfg)
	}
	panic(ErrorMsgPlatFormNameError)
}

// MergeExportedData
// 向外部暴露的合并借口，根据平台执行合并操作
// gitee包含：用户、Mr、Issue
// aone包含：用户、Mr
func MergeExportedData(cfg *common.Config) error {
	platformName := GetPlatformName(cfg.BaseConfig.ExportPlatformName)
	progress, err := ReadMergeProgress(cfg)
	if err != nil {
		return err
	}

	waitGroup := sync.WaitGroup{}
	for key, val := range MergeFuncMap[platformName] {
		finish := false
		for _, p := range progress {
			if p.TaskName == key {
				finish = p.Finish
				break
			}
		}

		if finish {
			cfg.GlobalLog.Info(key + "的Merge任务已完成，本次Merge跳过")
			continue
		}
		waitGroup.Add(1)
		go func(mergeName string, mergeFunc func(cfg *common.Config) error) {
			cfg.GlobalLog.Info(mergeName + "-Merge开始执行")
			err := mergeFunc(cfg)
			if err != nil {
				cfg.GlobalLog.Error(mergeName+"-Merge出现错误:", err)
			} else {
				for idx, p := range progress {
					if p.TaskName == mergeName {
						progress[idx].Finish = true
						break
					}
				}
				cfg.GlobalLog.Info(mergeName + "-Merge正确结束")
			}
			waitGroup.Done()
		}(key, val)
	}

	waitGroup.Wait()

	err = SaveMergeProgress(cfg, progress)

	if err != nil {
		return err
	}
	return nil
}

// ReadMergeProgress
// 读取Merge行为的进度文件
func ReadMergeProgress(cfg *common.Config) (TaskProgressArray, error) {
	platformName := GetPlatformName(cfg.BaseConfig.ExportPlatformName)

	tmplArgs := TmplArgs{
		ExportDataDir:      cfg.BaseConfig.ExportDataDir,
		ExportPlatformName: platformName,
		FileName:           MergeProgressFileName,
		EnterpriseName:     cfg.BaseConfig.EnterpriseName,
		StringTmpl:         ExportEnterpriseFileTmpl,
	}

	filePath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return nil, err
	}

	_, err = os.Stat(filePath)

	var progress TaskProgressArray
	for key := range MergeFuncMap[platformName] {
		taskProgress := TaskProgress{
			TaskName: key,
			Finish:   false,
		}
		progress = append(progress, taskProgress)
	}

	if err == nil && (cfg.BaseConfig.UseProgress || !cfg.BaseConfig.Export) {
		data, err := os.ReadFile(filePath)
		if err != nil {
			return nil, err
		}
		var processFile TaskProgressArray
		err = json.Unmarshal(data, &processFile)
		if err != nil {
			return nil, err
		}

		for _, val := range processFile {
			for idx, taskProgress := range progress {
				if taskProgress.TaskName == val.TaskName {
					progress[idx].Finish = val.Finish
				}
			}
		}
	} else if os.IsNotExist(err) {
	} else if err != nil {
		// 出现错误
		return nil, err
	}

	return progress, nil
}

// SaveMergeProgress
// 保存Merge行为的进度
func SaveMergeProgress(cfg *common.Config, progress TaskProgressArray) error {
	platformName := GetPlatformName(cfg.BaseConfig.ExportPlatformName)

	tmplArgs := TmplArgs{
		ExportDataDir:      cfg.BaseConfig.ExportDataDir,
		ExportPlatformName: platformName,
		FileName:           MergeProgressFileName,
		EnterpriseName:     cfg.BaseConfig.EnterpriseName,
		StringTmpl:         ExportEnterpriseFileTmpl,
	}

	filePath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	data, err := json.Marshal(progress)
	if err != nil {
		return err
	}
	err = os.WriteFile(filePath, data, os.ModePerm)
	if err != nil {
		return err
	}

	return nil
}

// UpdateMergeProgress
// 删除Merge行为的进度
func UpdateMergeProgress(cfg *common.Config) error {
	platformName := GetPlatformName(cfg.BaseConfig.ExportPlatformName)

	tmplArgs := TmplArgs{
		ExportDataDir:      cfg.BaseConfig.ExportDataDir,
		ExportPlatformName: platformName,
		FileName:           MergeProgressFileName,
		EnterpriseName:     cfg.BaseConfig.EnterpriseName,
		StringTmpl:         ExportEnterpriseFileTmpl,
	}

	filePath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(filePath)

	if os.IsNotExist(err) {
		var progress TaskProgressArray
		for key := range MergeFuncMap[platformName] {
			progress = append(progress, TaskProgress{
				TaskName: key,
				Finish:   false,
			})
		}
		return SaveMergeProgress(cfg, progress)
	}

	needUserMergeTaskMap := make(map[string]struct{})
	needUserMergeTaskMap[TaskNameRepoMember] = struct{}{}
	needUserMergeTaskMap[TaskNameMergeRequest] = struct{}{}
	needUserMergeTaskMap[TaskNameIssue] = struct{}{}
	needUserMergeTaskMap[GlobalTaskNameEnterpriseMember] = struct{}{}
	needUserMergeTaskMap[GlobalTaskNameGroupMember] = struct{}{}
	data, err := os.ReadFile(filePath)
	if err != nil {
		return err
	}
	var progress TaskProgressArray
	err = json.Unmarshal(data, &progress)
	if err != nil {
		return err
	}

	match := false
	for key := range needUserMergeTaskMap {
		for _, val := range cfg.BaseConfig.Feature {
			if match {
				break
			}
			// val为模版串
			re := regexp.MustCompile(val)
			// 使用模板穿匹配任务名
			m := re.MatchString(key)
			match = m || match
		}
	}

	if match {
		for idx := range progress {
			if progress[idx].TaskName == MergeNameUser {
				progress[idx].Finish = false
			}
		}
		err = SaveMergeProgress(cfg, progress)
		if err != nil {
			return err
		}
	}

	return nil
}

// CheckMergeFinished
// check是否有未完成的Merge行为
func CheckMergeFinished(cfg *common.Config) (bool, error) {
	progress, err := ReadMergeProgress(cfg)
	if err != nil {
		return false, err
	}

	for _, val := range progress {
		if !val.Finish {
			return false, nil
		}
	}

	return true, nil
}

// DeleteGlobalImportTaskProgress
// 完成一次导出后，需要删除上次导入任务的进度
func DeleteGlobalImportTaskProgress(cfg *common.Config) error {
	platformName := GetPlatformName(cfg.BaseConfig.ExportPlatformName)

	tmplArgs := TmplArgs{
		ExportDataDir:      cfg.BaseConfig.ExportDataDir,
		ExportPlatformName: platformName,
		FileName:           ImportProgressFileName,
		EnterpriseName:     cfg.BaseConfig.EnterpriseName,
		StringTmpl:         ExportEnterpriseFileTmpl,
	}

	filePath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(filePath)
	if err == nil {
		err = os.Remove(filePath)
		if err != nil {
			return err
		}
	}
	return nil
}

// ReadGlobalTaskProgress
// 读取不分库任务的进度
func ReadGlobalTaskProgress(cfg *common.Config) (TaskProgressArray, error) {
	platformName := GetPlatformName(cfg.BaseConfig.ExportPlatformName)

	tmplArgs := TmplArgs{
		ExportDataDir:      cfg.BaseConfig.ExportDataDir,
		ExportPlatformName: platformName,
		EnterpriseName:     cfg.BaseConfig.EnterpriseName,
		StringTmpl:         ExportEnterpriseFileTmpl,
	}

	if cfg.BaseConfig.Check {
		return nil, nil
	} else if cfg.BaseConfig.Export {
		tmplArgs.FileName = ExportProgressFileName
	} else {
		tmplArgs.FileName = ImportProgressFileName
		platformName = importPlatformMap[platformName]
	}

	filePath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return nil, err
	}

	var progress TaskProgressArray
	for key := range GlobalFuncMaps[platformName] {
		taskProgress := TaskProgress{
			TaskName: key,
			Finish:   false,
		}
		progress = append(progress, taskProgress)
	}
	//stat, err := os.Stat(filePath)
	_, err = os.Stat(filePath)
	if err == nil && cfg.BaseConfig.RepoUseProgress {
		//interval := time.Now().Sub(stat.ModTime())
		//// 在时间间隔内，认为进度文件是有效的，否则进度文件就是无效的
		//if interval.Seconds() < DefaultProgressTimeoutSeconds {
		data, err := os.ReadFile(filePath)
		if err != nil {
			return nil, err
		}
		var processFile TaskProgressArray
		err = json.Unmarshal(data, &processFile)
		if err != nil {
			return nil, err
		}

		for _, val := range processFile {
			for idx, taskProgress := range progress {
				if taskProgress.TaskName == val.TaskName {
					progress[idx].Finish = val.Finish
				}
			}
		}
		//}
	} else if os.IsNotExist(err) {
	} else if err != nil {
		// 出现错误
		return nil, err
	}
	return progress, nil
}

// SaveGlobalTaskProgress
// 保存不分库任务的进度
func SaveGlobalTaskProgress(cfg *common.Config, progress TaskProgressArray) error {
	platformName := GetPlatformName(cfg.BaseConfig.ExportPlatformName)

	tmplArgs := TmplArgs{
		ExportDataDir:      cfg.BaseConfig.ExportDataDir,
		ExportPlatformName: platformName,
		EnterpriseName:     cfg.BaseConfig.EnterpriseName,
		StringTmpl:         ExportEnterpriseFileTmpl,
	}

	if cfg.BaseConfig.Check {
		return nil
	} else if cfg.BaseConfig.Export {
		tmplArgs.FileName = ExportProgressFileName
	} else {
		tmplArgs.FileName = ImportProgressFileName
	}

	filePath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	data, err := json.Marshal(progress)
	if err != nil {
		return err
	}
	err = os.WriteFile(filePath, data, os.ModePerm)
	if err != nil {
		return err
	}

	if cfg.BaseConfig.Export {
		err = DeleteGlobalImportTaskProgress(cfg)
		if err != nil {
			return err
		}
	}

	return nil
}

// 不分库的全局函数入口
func StartGlobalTask(cfg *common.Config) error {
	platformName := GetPlatformName(cfg.BaseConfig.ExportPlatformName)
	recordArgs := RecordArgs{
		Log:    cfg.GlobalLog,
		Check:  cfg.BaseConfig.Check,
		Export: cfg.BaseConfig.Export,
	}

	var enterpriseId int64
	if platformName == GiteePlatformName {
		enterpriseId = -1
		page := 1
		tmplArgs := TmplArgs{
			PageSize:        cfg.BaseConfig.PageSize,
			EnterpriseToken: cfg.BaseConfig.EnterpriseToken,
			StringTmpl:      GiteeV8OpenApiGetAllAuthorizedEnterprise,
		}
		baseUrl, err := FillParamIntoStringTmpl(tmplArgs)
		if err != nil {
			return err
		}

		for {
			realUrl := baseUrl + strconv.Itoa(page)
			page += 1
			var enterpriseList gitee.V8EnterpriseList
			requestArgs := giteeRequestArgs{
				RequestArgs: RequestArgs{
					ExportPlatformName: GiteePlatformName,
					RealUrl:            realUrl,
					RetVal:             &enterpriseList,
				},
				TaskName: "get-enterprise-list",
				Log:      cfg.GlobalLog,
			}

			if err = giteeDoGetRequest(requestArgs); err != nil {
				return err
			}

			if len(enterpriseList.Data) == 0 {
				break
			}

			for _, val := range enterpriseList.Data {
				if val.Name == cfg.BaseConfig.EnterpriseName {
					enterpriseId = val.ID
					break
				}
			}

			if enterpriseId != -1 {
				break
			}
		}

		if enterpriseId == -1 {
			return errors.New("未找到企业信息，请修改配置文件")
		}

	}

	args := TaskArgs{
		RepoInfo: &RepoInfo{
			EnterpriseId: enterpriseId,
		},
		ExportDataDir:      cfg.BaseConfig.ExportDataDir,
		Log:                cfg.GlobalLog,
		Token:              cfg.BaseConfig.Token,
		EnterpriseToken:    cfg.BaseConfig.EnterpriseToken,
		EnterpriseName:     cfg.BaseConfig.EnterpriseName,
		PageSize:           cfg.BaseConfig.PageSize,
		ExportPlatformName: platformName,
	}

	if !cfg.BaseConfig.Export {
		conn, err := CreateGrpcConnect(&cfg.BaseConfig)
		if err != nil {
			return err
		}
		args.Conn = conn
		args.AppKey = cfg.BaseConfig.AppKey
		args.AppSecret = cfg.BaseConfig.AppSecret

		platformName = importPlatformMap[platformName]
	}

	if cfg.BaseConfig.Check {
		args.Write = cfg.BaseConfig.Write
	}

	progress, err := ReadGlobalTaskProgress(cfg)
	if err != nil {
		return err
	}

	var funcMaps map[string]func(args TaskArgs) error
	if cfg.BaseConfig.Check {
		funcMaps = GlobalCheckFuncMaps[platformName]
	} else {
		funcMaps = GlobalFuncMaps[platformName]
	}

	var globalError error
	globalError = nil
	waitGroup := sync.WaitGroup{}
	atLeastOneTask := false
	for taskName, fun := range funcMaps {
		match := false
		for _, feature := range cfg.BaseConfig.GlobalFeature {
			match, err = regexp.MatchString(feature, taskName)
			if err != nil {
				return err
			}
			if match {
				break
			}
		}
		if !match {
			continue
		}

		args.TaskName = taskName
		recordArgs.TaskName = taskName
		if !cfg.BaseConfig.Check {
			skipTask := false
			for _, taskProgress := range progress {
				if taskProgress.TaskName == taskName {
					if taskProgress.Finish {
						recordArgs.Msg = "根据进度查询，任务已经完成，本次执行跳过"
						recordTask(recordArgs)
						skipTask = true
						break
					}
				}
			}
			if skipTask {
				continue
			}
		}
		recordArgs.Msg = "任务准备开始"
		recordTask(recordArgs)
		atLeastOneTask = true
		waitGroup.Add(1)
		go func(args TaskArgs, recordArgs RecordArgs, f func(args TaskArgs) error) {
			err := f(args)
			finish := true
			if err != nil {
				globalError = err
				finish = false
				recordArgs.Err = err
				recordArgs.Msg = "任务执行结束"
			} else {
				recordArgs.Msg = "任务成功执行！"
			}
			recordTask(recordArgs)
			if !cfg.BaseConfig.Check {
				for idx, taskProgress := range progress {
					if taskProgress.TaskName == args.TaskName {
						progress[idx].Finish = finish
						break
					}
				}
			}
			waitGroup.Done()
		}(args, recordArgs, fun)
	}

	waitGroup.Wait()
	if atLeastOneTask {
		err = SaveGlobalTaskProgress(cfg, progress)
	}
	if globalError != nil {
		return globalError
	}
	if err != nil {
		return err
	}

	return nil
}

func RemoveIncrement(cfg *common.Config) error {
	repos, err := GetAllRepoInfo(cfg)
	if err != nil {
		return err
	}
	for _, repo := range repos {
		err = RemoveMergeRequestIncrement(&repo, &cfg.BaseConfig)
		if err != nil {
			return err
		}
		err = RemoveMergeRequestMergeFile(&repo, &cfg.BaseConfig)
		if err != nil {
			return err
		}
		err = RemoveIssueIncrement(&repo, &cfg.BaseConfig)
		if err != nil {
			return err
		}
		err = RemoveIssueMergeFile(&repo, &cfg.BaseConfig)
		if err != nil {
			return err
		}
	}

	return nil
}

func RemoveMergeRequestIncrement(repo *RepoInfo, cfg *common.BaseConfig) error {
	tmplArgs := TmplArgs{
		StringTmpl:         ExportDataFileTmpl,
		RepoGroupName:      repo.RepoGroupName,
		RepoName:           repo.RepoName,
		ExportDataDir:      cfg.ExportDataDir,
		ExportPlatformName: cfg.ExportPlatformName,
		FileName:           BinFileNameMergeRequestsIncrement,
	}

	filepath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(filepath)
	if err == nil {
		err = os.Remove(filepath)
		if err != nil {
			return err
		}
	}

	tmplArgs.FileName = BinFileNameMergeRequestUsersIncrement
	filepath, err = FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(filepath)
	if err == nil {
		err = os.Remove(filepath)
		if err != nil {
			return err
		}
	}

	return nil
}

func RemoveIssueIncrement(repo *RepoInfo, cfg *common.BaseConfig) error {
	tmplArgs := TmplArgs{
		StringTmpl:         ExportDataFileTmpl,
		RepoGroupName:      repo.RepoGroupName,
		RepoName:           repo.RepoName,
		ExportDataDir:      cfg.ExportDataDir,
		ExportPlatformName: cfg.ExportPlatformName,
		FileName:           BinFileNameIssuesIncrement,
	}

	filepath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(filepath)
	if err == nil {
		err = os.Remove(filepath)
		if err != nil {
			return err
		}
	}

	tmplArgs.FileName = BinFileNameIssueUsersIncrement
	filepath, err = FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(filepath)
	if err == nil {
		err = os.Remove(filepath)
		if err != nil {
			return err
		}
	}

	return nil
}

func RemoveMergeRequestMergeFile(repo *RepoInfo, cfg *common.BaseConfig) error {
	tmplArgs := TmplArgs{
		StringTmpl:         ExportDataFileTmpl,
		RepoGroupName:      repo.RepoGroupName,
		RepoName:           repo.RepoName,
		ExportDataDir:      cfg.ExportDataDir,
		ExportPlatformName: cfg.ExportPlatformName,
		FileName:           BinFileNameMergeRequestsMerge,
	}

	filepath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(filepath)
	if err == nil {
		err = os.Remove(filepath)
		if err != nil {
			return err
		}
	}
	return nil
}

func RemoveIssueMergeFile(repo *RepoInfo, cfg *common.BaseConfig) error {
	tmplArgs := TmplArgs{
		StringTmpl:         ExportDataFileTmpl,
		RepoGroupName:      repo.RepoGroupName,
		RepoName:           repo.RepoName,
		ExportDataDir:      cfg.ExportDataDir,
		ExportPlatformName: cfg.ExportPlatformName,
		FileName:           BinFileNameIssuesMerge,
	}

	filepath, err := FillParamIntoStringTmpl(tmplArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(filepath)
	if err == nil {
		err = os.Remove(filepath)
		if err != nil {
			return err
		}
	}
	return nil
}

func CopyRepoInfo(repo *RepoInfo) *RepoInfo {
	return &RepoInfo{
		EnterpriseId:     repo.EnterpriseId,
		CodeCloneHttpUrl: repo.CodeCloneHttpUrl,
		WikiEnable:       repo.WikiEnable,
		RepoId:           repo.RepoId,
		RepoName:         repo.RepoName,
		RepoGroupId:      repo.RepoGroupId,
		RepoGroupName:    repo.RepoGroupName,
	}
}
